#include <utility/spw_move_in.h>
#include <type_traits>

#include <gtest/gtest.h>

using namespace spwstd;
using namespace spwstd::spwuti;
TEST(MoveTest, Move) {
    const int a = 1;
    EXPECT_TRUE(std::is_rvalue_reference<decltype(spwuti::move(a))>::value);
    EXPECT_TRUE(std::is_rvalue_reference<decltype(spwuti::move(12))>::value);
}

// 保留cv属性，并保留左，右值属性
TEST(ForwardTest, Forward) {
    const int& a=1;
    int b = 11;
    int& c = b;
    // forward<const int>
    // 如果当为forward<int>时，forward<int>(a)则报错，因为a为const int&, 而forward(int&)无法接收a作为参数
    // const int&& forward(const int& x) { return static_cast<const int&&>(xx); }
    EXPECT_TRUE(
            std::is_rvalue_reference<
                decltype(spwuti::forward<const int>(a))
            >::value);
    EXPECT_TRUE(
            std::is_rvalue_reference<
                decltype(spwuti::forward<const int>(b))
            >::value);
    EXPECT_TRUE(
            std::is_rvalue_reference<
                decltype(spwuti::forward<const int>(c))
            >::value);
    // const int&& forward(const int&& x) { return static_cast<const int&&>(x)}
    EXPECT_TRUE(
            std::is_rvalue_reference<
                decltype(spwuti::forward<const int>(12))
            >::value);

    // forward<const int>(xx)返回类型const int&&
    EXPECT_TRUE(
            std::is_const<
                std::remove_reference<
                    decltype(spwuti::forward<const int>(12))
                >::type
            >::value);
    EXPECT_TRUE(
            std::is_const<
                std::remove_reference<
                    decltype(spwuti::forward<const int>(a))
                >::type
            >::value);
    EXPECT_TRUE(
            std::is_const<
                std::remove_reference<
                    decltype(spwuti::forward<const int>(b))
                >::type
            >::value);
    EXPECT_TRUE(
            std::is_const<
                std::remove_reference<
                    decltype(spwuti::forward<const int>(c))
                >::type
            >::value);
}

struct SwapInt {
    int test;
    SwapInt(int a): test(a){}
    operator int(){ return test; }
    SwapInt(const SwapInt&)=default;
    SwapInt& operator=(const SwapInt&)=default;

    // 不可显示delete，会匹配到该operator=
    // 而无法调用拷贝operator=
    // SwapInt& operator=(SwapInt&&)=delete;
};

TEST(SwapTest, Swap) {
// 通用swap
    SwapInt test1(111);
    // int test3 = 333;
    // int test2 = 222;
    SwapInt test2(222);
    spwuti::swap(test1, test2);
    EXPECT_EQ(test1.test, 222);
    EXPECT_EQ(test2.test, 111);
    // 错误, 类型不一样 SwapInt != int
    // spwuti::Swap(test1, test2);
    // std::swap(test1, test2);
    //
    // 错误, static_cast<int>()是一个右值，没办法传入T&
    // spwuti::Swap(static_cast<int>(test1), test2);
    // std::swap(static_cast<int>(test1), test2);

// 数组特化
    SwapInt arr1[3]{1,2,3};
    SwapInt arr2[3]{4,5,6};
    spwuti::swap(arr1, arr2);
    EXPECT_EQ(arr1[0].test, 4);
    EXPECT_EQ(arr1[2].test, 6);
    EXPECT_EQ(arr2[0].test, 1);
    EXPECT_EQ(arr2[2].test, 3);
}

#include <memory/spw_new.h>
template<typename T>
struct Ptr{
    T* pad;
    T* data;
    Ptr(T* arg): pad(nullptr), data(arg) {}

    ~Ptr() { delete data; }
    T** operator&() { return &data; }
};

template<class T>
int f(Ptr<T>*){
    return 1111;
}
int f(int**) {
    return 2222;
}

TEST(Addressoftest, Addressof){
    Ptr<int> p(new int(42));    
    EXPECT_TRUE(1111 == f(addressOf(p))) << "value is " << f(addressOf(p));
    EXPECT_TRUE(2222 == f(&p)) << "value is" << f(&p);
}
